﻿using Microsoft.Extensions.Logging;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using VIA.Integration.Domain.Production;
using VIA.Integration.Domain;
using VIA.VTPlatformService;
using static VT.Framework.Utils.UtilMiniDump;
using VT.Framework.Scene2D.Structs;
using VIA.ImageProcessing;
using VT.Framework.Designer.Flow;
using VIA.SiMoJi.Domain.Option;
using VT.Framework.Vision2D.Tools.Detect;
using VT.Framework.Vision2D.VT2D;
using VT.Framework.Vision2D.Tools.Location;
using OpenCvSharp;
using System.Drawing;

namespace VIA.SiMoJi.Domain.Vision
{
    public interface IImageDetecter
    {
        TopImageAlgorithmResult TopImageDetect(ImageData image, VTFlowBlockInfo blockInfo);
        TopImageAlgorithmResult TopImageDetectMark(ImageData image, VTFlowBlockInfo blockInfo);
        BottomDuiWeiAlgorithmResult BottomImageDuiWei(ImageData image, VTFlowBlockInfo blockInfo);
        BottomDetectAlgorithmResult BottomImageDetect(ImageData image, VTFlowBlockInfo blockInfo);
        UpImageAlgorithmResult UpImageDetect(ImageData image, VTFlowBlockInfo blockInfo);

    }
    public class ImageDetecter : IImageDetecter
    {
        private readonly ILogger _logger;
        private readonly IVTPlatformManager _platformManager;

        public ImageDetecter(ILogger<ImageDetecter> logger, IVTPlatformManager platformManager)
        {
            _logger = logger;
            _platformManager = platformManager;
        }

        public BottomDuiWeiAlgorithmResult BottomImageDuiWei(ImageData image, VTFlowBlockInfo blockInfo)
        {
            var result = new BottomDuiWeiAlgorithmResult(image);
            using var blockWrapper = _platformManager.GetBlockWrapper(blockInfo);
            var block = blockWrapper?.VTFlowBlock;
            if (block == null) return result;
            block.Inputs["In"].Value = image.ToVImage8Grey();
            block.Run();
            if (block.Status.Result == ERunResultType.Success)
            {
                string barcode = string.Empty;
                if (block.Outputs.ContainsKey("barcode"))
                {
                    barcode = (string)block.Outputs["barcode"].Value;
                }
                else
                {
                    barcode = "NotBarcode";
                }
                VLine line1 = (VLine)block.Outputs["line1"].Value;
                //VLine line2 = (VLine)block.Outputs["line2"].Value;
                VCircle circle = (VCircle)block.Outputs["circle"].Value;
                VPoint point = (VPoint)block.Outputs["point"].Value;
                double angle = (double)block.Outputs["angle"].Value;
                result.Pose = new Pose(point.X, point.Y, angle);
                result.Barcode = barcode;
                result.AddStroke(new DrawableLine(line1.ToVIALine()) { Stroke = System.Drawing.Color.Green, StrokeThickness = 2 });
                result.AddStroke(new DrawableCircle(circle.ToVIACircle(), 2, System.Drawing.Color.Green) { Stroke = System.Drawing.Color.Green, StrokeThickness = 2 });
                //result.AddStroke(new DrawableLine(line2.ToVIALine()) { Stroke = System.Drawing.Color.Green, StrokeThickness = 2 });
            }
            else
            {
                result.AddMessage($"运行失败:{block.Status.ErrorMessage}", Quality.Ng);
            }
            return result;
        }

        public BottomDetectAlgorithmResult BottomImageDetect(ImageData image, VTFlowBlockInfo blockInfo)
        {
            var result = new BottomDetectAlgorithmResult(image);
            using var blockWrapper = _platformManager.GetBlockWrapper(blockInfo);
            var block = blockWrapper?.VTFlowBlock;
            if (block == null) return result;
            block.Inputs["In"].Value = image.ToVImage8Grey();
            block.Run();
            if (block.Status.Result == ERunResultType.Success)
            {
                result.IsSiMoOK = (bool)block.Outputs["isOK"].Value;
            }
            else
            {
                result.AddMessage($"运行失败:{block.Status.ErrorMessage}", Quality.Ng);
            }
            return result;
        }

        public TopImageAlgorithmResult TopImageDetect(ImageData image, VTFlowBlockInfo blockInfo)
        {
            var result = new TopImageAlgorithmResult(image);
            using var blockWrapper = _platformManager.GetBlockWrapper(blockInfo);
            var block = blockWrapper?.VTFlowBlock;
            if (block == null) return result;
            block.Inputs["In"].Value = image.ToVImage8Grey();
            block.Run();
            if (block.Status.Result == ERunResultType.Success)
            {
                List<bool> hasProducts = new List<bool>();
                VCoord coord = (VCoord)block.Outputs["vcoord"].Value;
                VLine line1 = (VLine)block.Outputs["line1"].Value;
                VLine line2 = (VLine)block.Outputs["line2"].Value;
                var grayTools = (List<VTGetGrayInfoTool>)block.Outputs["GrayTools"].Value;
                result.IsTrayReverseOK = (bool)block.Outputs["Tray"].Value;
                double gray = (int)block.Outputs["KakongGray"].Value;//以下是有产品
                double uppergray = (int)block.Outputs["KakongGrayUpper"].Value;//以上是无产品  在gray与uppergray之间表示搭边
                var tempHasProducts = new bool[84];
                foreach (var grayTool in grayTools)
                {
                    string propName = grayTool.PropName;
                    double meanGray = grayTool.MeanGray;
                    var number = Convert.ToInt32(propName.Replace("灰度信息", string.Empty));
                    var rectangle = grayTool.GetROI().GetBoundingBox();
                    int isHasProduct = 0;
                    Color color = Color.Green;
                    if (meanGray < gray)
                    {
                        isHasProduct = 1;
                        color = Color.Green;
                        tempHasProducts[number - 1] = true;
                    }
                    else if (meanGray > uppergray)
                    {
                        isHasProduct = 2;
                        tempHasProducts[number - 1] = false;
                    }
                    else
                    {
                        isHasProduct = 3;
                        color = Color.Red;
                    }                    
                    if (isHasProduct == 3)
                    {
                        var drawableRect = new DrawableRect(new VIARect(rectangle.CenterX - 20, rectangle.CenterY - 20, 50, 50), 5, color);
                        drawableRect.Text = (number - 1).ToString();
                        drawableRect.FontSize = 24;
                        result.AddStroke(drawableRect);
                    }
                }
                var frontList = GetVCoords(block, "Front");
                var frontCount = frontList.Count;
                for (int i = 0; i < frontList.Count(); i++)
                {
                    var frontItem = frontList[i];
                    var drawableRectFront = new DrawableRect(new VIARect(frontItem.X - 50, frontItem.Y - 160, 150, 340), 2, Color.Green);
                    result.AddStroke(drawableRectFront);
                }
                var backList = GetVCoords(block, "Back");
                var backCount = backList.Count;
                for (int i = 0; i < backList.Count(); i++)
                {
                    var backItem = backList[i];
                    var drawableRectBack = new DrawableRect(new VIARect(backItem.X - 100, backItem.Y - 160, 150, 340), 2, Color.Green);
                    result.AddStroke(drawableRectBack);
                }
                List<bool> fronts = new List<bool>();//正方向
                List<bool> backs = new List<bool>();
                for (int i = 0; i < tempHasProducts.Count(); i++)
                {
                    if (i % 14 <= 6) // 等价于 i % 14 ∈ [0,6]
                    {
                        fronts.Add(tempHasProducts[i]);
                    }
                    else // 等价于 i % 14 ∈ [7,13]
                    {
                        backs.Add(tempHasProducts[i]);
                    }
                }
                //正方向（第一排这种）全图匹配到的正方向产品数量，如果zheng = 42 - 正方向空穴数量，则正常，若不等则异常。
                var frontNoneCount = (42 - fronts.Count(x => x == false));
                if (frontCount != frontNoneCount)
                {
                    result.AddMessage($"产品正搭边", Quality.Ng);
                }
                else
                {
                    result.AddMessage($"产品正数量{frontCount}", Quality.Ok);
                }
                //反方向（第二排这种）全图匹配到的反方向产品数量，如果zheng=42-反方向空穴数量，则正常，若不等则异常。
                var backNoneCount = (42 - backs.Count(x => x == false));
                if (backCount != backNoneCount)
                {
                    result.AddMessage($"产品反搭边", Quality.Ng);
                }
                else
                {
                    result.AddMessage($"产品反数量{backCount}", Quality.Ok);
                }
                result.HasProducts = tempHasProducts.ToArray();
                result.Pose = new Pose(coord.X, coord.Y, coord.R);
                result.AddStroke(new DrawableLine(line1.ToVIALine()) { Stroke = System.Drawing.Color.Green, StrokeThickness = 2 });
                result.AddStroke(new DrawableLine(line2.ToVIALine()) { Stroke = System.Drawing.Color.Green, StrokeThickness = 2 });
            }
            else
            {
                result.AddMessage($"运行失败:{block.Status.ErrorMessage}", Quality.Ng);
            }
            return result;

            #region TODO
            //var result = new TopImageAlgorithmResult(image);
            //using var blockWrapper = _platformManager.GetBlockWrapper(blockInfo);
            //var block = blockWrapper?.VTFlowBlock;
            //if (block == null) return result;
            //block.Inputs["In"].Value = image.ToVImage8Grey();
            //block.Run();
            //if (block.Status.Result == ERunResultType.Success)
            //{
            //    //VTFindShapeModelTool model = new();
            //    VCoord coord = (VCoord)block.Outputs["vcoord"].Value;
            //    VLine line1 = (VLine)block.Outputs["line1"].Value;
            //    VLine line2 = (VLine)block.Outputs["line2"].Value;
            //    List<bool> hasProducts = (List<bool>)block.Outputs["hasProducts"].Value;//产品有无集合,True表示有产品,False表示无产品
            //    List<string> allResultsString = (List<string>)block.Outputs["AllResultsString"].Value;//产品灰度信息
            //    result.IsTrayReverseOK = (bool)block.Outputs["Tray"].Value;
            //    var tempHasProducts = new bool[hasProducts.Count()];
            //    for (int i = 0; i < allResultsString.Count(); i++)//平台里面84到1
            //    {
            //        string resultName = allResultsString[i];
            //        var number = Convert.ToInt32(resultName.Replace("灰度信息", string.Empty));
            //        tempHasProducts[number - 1] = hasProducts[i];
            //    }
            //    result.HasProducts = tempHasProducts.ToArray();//这里是正序了1-84
            //    if (hasProducts.Any(x => x == true))//如果空盘就不判断
            //    {
            //        int frontCount = 0;
            //        int backCount = 0;
            //        var allSideResults = new List<bool>();
            //        if (block.Outputs.ContainsKey("AllSideResults"))
            //        {
            //            allSideResults = ((List<bool>)block.Outputs["AllSideResults"].Value);
            //        }
            //        if (block.Outputs.ContainsKey("Front"))
            //        {
            //            if (block.Outputs["Front"].Value != null)
            //            {
            //                frontCount = ((List<VCoord>)block.Outputs["Front"].Value).Count();
            //                var frontList = ((List<VCoord>)block.Outputs["Front"].Value);
            //                foreach (var frontItem in frontList)
            //                {
            //                    var drawableRect = new DrawableRect(new VIARect(frontItem.X + 50, frontItem.Y - 80, 50, 100), 5, Color.Green);
            //                    drawableRect.Text = "1";
            //                    drawableRect.FontSize = 24;
            //                    result.AddStroke(drawableRect);
            //                }
            //            }
            //        }
            //        if (block.Outputs.ContainsKey("Back"))
            //        {
            //            if (block.Outputs["Back"].Value != null)
            //            {
            //                backCount = ((List<VCoord>)block.Outputs["Back"].Value).Count();
            //            }
            //        }
            //        List<bool> fronts = new List<bool>();//正方向
            //        List<bool> backs = new List<bool>();
            //        List<string> strings1 = new List<string>();
            //        List<string> strings2 = new List<string>();
            //        //for (int i = 0; i < tempHasProducts.Count(); i++)
            //        //{
            //        //    if ((i >= 0 && i <= 6) || (i >= 14 && i <= 20) || (i >= 28 && i <= 34) || (i >= 42 && i <= 48) || (i >= 56 && i <= 62) || (i >= 70 && i <= 76))
            //        //    {
            //        //        fronts.Add(tempHasProducts[i]);
            //        //        strings1.Add(i.ToString());
            //        //    }
            //        //    else if ((i >= 7 && i <= 13) || (i >= 21 && i <= 27) || (i >= 35 && i <= 41) || (i >= 49 && i <= 55) || (i >= 63 && i <= 69) || (i >= 77 && i <= 83))
            //        //    {
            //        //        backs.Add(tempHasProducts[i]);
            //        //        strings2.Add(i.ToString());
            //        //    }
            //        //}
            //        for (int i = 0; i < tempHasProducts.Count(); i++)
            //        {
            //            if (i % 14 <= 6) // 等价于 i % 14 ∈ [0,6]
            //            {
            //                fronts.Add(tempHasProducts[i]);
            //                strings1.Add(i.ToString());
            //            }
            //            else // 等价于 i % 14 ∈ [7,13]
            //            {
            //                backs.Add(tempHasProducts[i]);
            //                strings2.Add(i.ToString());
            //            }
            //        }
            //        //正方向（第一排这种）全图匹配到的正方向产品数量，如果zheng=42-正方向空穴数量，则正常，若不等则异常。
            //        var frontNoneCount = (42 - fronts.Count(x => x == false));
            //        if (frontCount != frontNoneCount)
            //        {
            //            result.AddMessage($"产品正数量异常", Quality.Ng);
            //        }
            //        else
            //        {
            //            result.AddMessage($"产品正数量{frontCount}", Quality.Ok);
            //        }
            //        //反方向（第二排这种）全图匹配到的反方向产品数量，如果zheng=42-反方向空穴数量，则正常，若不等则异常。
            //        var backNoneCount = (42 - backs.Count(x => x == false));
            //        if (backCount != backNoneCount)
            //        {
            //            result.AddMessage($"产品反数量异常", Quality.Ng);
            //        }
            //        else
            //        {
            //            result.AddMessage($"产品反数量{backCount}", Quality.Ok);
            //        }
            //        //满料Tary拍照得到产品灰度在 a 以下，空Tary拍照得到产品灰度在 b 以上，对比正常流程检测时84个穴位灰度，如果有穴位  a<灰度<b，则异常。
            //        if (allSideResults.Any(x => x))
            //        {
            //            result.AddMessage("产品定位异常", Quality.Ng);
            //        }
            //    }
            //    result.Pose = new Pose(coord.X, coord.Y, coord.R);
            //    result.AddStroke(new DrawableLine(line1.ToVIALine()) { Stroke = System.Drawing.Color.Green, StrokeThickness = 2 });
            //    result.AddStroke(new DrawableLine(line2.ToVIALine()) { Stroke = System.Drawing.Color.Green, StrokeThickness = 2 });
            //}
            //else
            //{
            //    result.AddMessage($"运行失败:{block.Status.ErrorMessage}", Quality.Ng);
            //}
            //return result;
            #endregion
        }

        List<VCoord> GetVCoords(VTFlowBlock flowBlock, string key)
        {
            if (flowBlock.Outputs[key].Value != null)
            {
                return (List<VCoord>)flowBlock.Outputs[key].Value;
            }
            return new List<VCoord>();
        }

        public TopImageAlgorithmResult TopImageDetectMark(ImageData image, VTFlowBlockInfo blockInfo)
        {
            var result = new TopImageAlgorithmResult(image);
            using var blockWrapper = _platformManager.GetBlockWrapper(blockInfo);
            var block = blockWrapper?.VTFlowBlock;
            if (block == null) return result;
            block.Inputs["In"].Value = image.ToVImage8Grey();
            block.Run();
            if (block.Status.Result == ERunResultType.Success)
            {
                VTFindShapeModelTool model = new();
                VCoord coord = (VCoord)block.Outputs["vcoord"].Value;
                VLine line1 = (VLine)block.Outputs["line1"].Value;
                VLine line2 = (VLine)block.Outputs["line2"].Value;
                result.Pose = new Pose(coord.X, coord.Y, coord.R);
                result.AddStroke(new DrawableLine(line1.ToVIALine()) { Stroke = System.Drawing.Color.Green, StrokeThickness = 2 });
                result.AddStroke(new DrawableLine(line2.ToVIALine()) { Stroke = System.Drawing.Color.Green, StrokeThickness = 2 });
            }
            else
            {
                result.AddMessage($"运行失败:{block.Status.ErrorMessage}", Quality.Ng);
            }
            return result;
        }

        public UpImageAlgorithmResult UpImageDetect(ImageData image, VTFlowBlockInfo blockInfo)
        {
            var result = new UpImageAlgorithmResult(image);
            using var blockWrapper = _platformManager.GetBlockWrapper(blockInfo);
            var block = blockWrapper?.VTFlowBlock;
            if (block == null) return result;
            block.Inputs["In"].Value = image.ToVImage8Grey();
            block.Run();
            if (block.Status.Result == ERunResultType.Success)
            {
                string barcode = (string)block.Outputs["barcode"].Value;
                VPaths paths = (VPaths)block.Outputs["roi"].Value;

                for (int i = 0; i < paths.Count; i++)
                {
                    List<VIAPoint> points = new List<VIAPoint>();
                    var path = paths[i];
                    for (int j = 0; j < path.Data.Count; j++)
                    {
                        points.Add(path.Data[j].ToVIAPoint());
                    }
                    VIAPolygon polygon = new VIAPolygon(points.ToArray());
                    result.AddStroke(new DrawablePolygon() { Polygon = polygon, Stroke = System.Drawing.Color.Green, StrokeThickness = 2 });
                }
                result.Barcode = barcode;
                result.AddMessage($"条码: {result.Barcode}", Quality.Ok);
            }
            else
            {
                result.AddMessage($"运行失败:{block.Status.ErrorMessage}", Quality.Ng);
            }
            return result;
        }

        public Pose GetFeedTrayOffset(Pose pose, Pose feedTrayMarkPoint, double resolution)
        {
            double deltX = pose.X - feedTrayMarkPoint.X;
            double deltY = pose.Y - feedTrayMarkPoint.Y;
            double deltAngle = pose.Angle - feedTrayMarkPoint.Angle;
            return new Pose(deltX * resolution, deltY * resolution, deltAngle);
        }

    }
}
